在程式碼中,我們常常因為需要在一個功能當中觸發不同的 side effect,會導致一段 function 中,會參雜其他功能的判斷和觸發,而這些功能到最後越來越龐大時,就會變能難以維護的一段 code,這些觸發和判斷就是 side effect,另外程式碼依賴其他程式碼功能很深時,就叫做高耦合。
這邊為了讓每段程式都讓他只做該做的事時,我們就必須遵守單一功能原則,讓每段程式碼只做他該做的事。譬如下面有一段 code,是實踐要個人資料的功能,在打 api 驗證失敗後會觸發 popup,接著按下 popup 上的按鈕會觸發其他事件。
// Profile.jsx
import {useEffect, useCallback ,useState} from 'react';
import loginAPI from './api.js';
import axios from 'axios'; //axios 為前端一套處理 call api 的套件
const Profile = ()=>{
const [userData,updataUserData] = useState({});
const [userError,updateUserError] = useState('');
const fecthUser = useCallback(async(url)=>{
try{
const result = await axios.get(url);
if(result.status === 200 && result.data
&& Object.keys(result.data)?.length > 0){
userData(result.data);
}else{
updateUserError(result.error??'');
}
}catch(err){
console.log('fetch uset error',err);
}
},[userData]);
useEffect(()=>{
fecthUser();
},[]);
return (
<div>
{Object.keys(userData).length > 0 &&
<>
<div>Name:{userData.name}</div>
<div>Name:{userData.email}</div>
<div>Name:{userData.phone}</div>
</>
}
{userError && <div>{userError}</div>}
</div>)
}
export default Profile;
上面的程式碼我們可以發現,當在 callapi 時,在 fetch login api 後,直接在 fetchUser 的 function 處理 存資料和 errorHandle,這邊會造成各個資料綁在一起,假如 popup 發現不正確,這時候我們就必須要去 fetchUser 找究竟哪個程式碼有錯。
比較好的方式是我們把整段程式分成幾個部分,讓他們的 function 都做自己的功能
// fetchUser function 改成 useFetchAPI function
import {useRef, useEffect} from 'react';
import axios from 'axios';
export default useFetchAPI(url,options){
const [data,setData] = useState(null);
const [error,setError] = useState(null);
const urlRef = useRef('');
if(!url || urlRef.current === url){
return;
};
const callApi = useCallback((url,method = 'get',data:{})=>{
return axios({
method,
url,
data;
});
},[])
useEffect(()=>{
callApi(url,options.method,options.data)
.then((res)=>{
if(result.status === 200 && result.data
&& Object.keys(result.data)?.length > 0){
userData(result.data);}
})
.catch(err=>{
setError(result.error);
})
},[url])
return {
data,
error
}
}
這時候我們可以發現,callapi 只要專注在拿資料的處理
而狀態的處理則交給,setData 和 setError,同時 setData 和 setError 不會對 callapi 內部造成影響。